#include "Driver.h"
#include "Mensaje.h"
#include "Reglas.h"

#include <iostream>
#include <sstream>

Driver::Driver() {
	reglas = new Reglas();
	redSocial = NULL;
	dia = 0;
	ticks = 0;
}

Driver::~Driver() {
	delete reglas;
	// la red social se destruye si fue creada
	if (redSocial != NULL)
		delete redSocial;
}

void Driver::agregarPaises(int cantidadPaises) {
	for (int i = 0; i < cantidadPaises; i++) {
		reglas->agregarPais();
	}
}

void Driver::restringirVer(int p1, int p2) {
	reglas->restringirVer(p1, p2);
}

bool Driver::tieneAlgunHueco() {
	return reglas->tieneAlgunHueco();
}

void Driver::avanzarDia(int c) {
	dia+=c;
	ticks=0;
}

void Driver::avanzarTick(int c) {
	ticks+=c;
}

void Driver::registrar(string u, int p) {
	// se crea la red social al registrar el primer usuario
	if (redSocial == NULL)
		redSocial = new RedSocial(reglas);

	redSocial->registrar(u, p);
}

void Driver::solicitaAmistad(string u1, string u2) {
	redSocial->quererSerAmigo(u1, u2);
}

bool Driver::sonAmigos(string u1, string u2) {
	return redSocial->sonAmigos(u1, u2);
}

bool Driver::quiereSerAmigo(string u1, string u2) {
	return redSocial->quiereSerAmigo(u1, u2);
}

void Driver::publicar(string autor, string contenido, Lista<string> tags) {
	// el mensaje se crea en el heap y pasa a ser responsabilidad
	// de la redSocial el eliminarlo cuando ya no se necesite
	Conj<string> cTags;
	for (Nat i = 0; i < tags.Longitud(); i++){
        cTags.Agregar(tags[i]);
	}
	Mensaje* m = new Mensaje(autor, contenido, ahora(), cTags);
	redSocial->publicar(m);
    avanzarTick(1); // avanzamos por default la marca de tiempo, sin cambiar de dia
}

int Driver::cantidadMensajesVisibles(string u) {
	ListaOrd::ItListaOrd it = redSocial->mensajesVisibles(u);
	int res = 0;
	while(it.HayMas()) {
		res++;
		it.Avanzar();
	}
	return res;
}

string Driver::mensajeVisible(string u, int i) {
	ListaOrd::ItListaOrd it = redSocial->mensajesVisibles(u);
	for(int j = 0; j < i; j++) {
		it.Avanzar();
	}
	const Mensaje* m = it.Actual();
	Lista<string> lTags;
	Conj<string>::const_Iterador itC;
	itC = (m->tags).CrearIt();
	while (itC.HaySiguiente()){
        lTags.AgregarAdelante(itC.Siguiente());
        itC.Avanzar();
	}
	return mostrarMensaje(m->usuario, m->contenido, lTags);
}

int Driver::cantidadMensajesRecientes(string u) {

	ListaOrd::ItListaTemp it = redSocial->mensajesVisiblesRecientes(u);
	int res = 0;
	while(it.HayMas()) {
		res++;
		it.Avanzar();
	}
	return res;
}

string Driver::mensajeReciente(string u, int i) {
	ListaOrd::ItListaTemp it = redSocial->mensajesVisiblesRecientes(u);
	for(int j = 0; j < i; j++) {
		it.Avanzar();
	}
	const Mensaje* m = it.Actual();
	Lista<string> lTags;
	Conj<string>::const_Iterador itC;
	itC = (m->tags).CrearIt();
	while (itC.HaySiguiente()){
        lTags.AgregarAtras(itC.Siguiente());
        itC.Avanzar();
	}
	return mostrarMensaje(m->usuario, m->contenido, lTags);
}

int Driver::cantidadTagsRecientes() {
	RedSocial::ItListaTags it = redSocial->tagsRecientes();
	int res = 0;

        while(it.hayMas()) {
            res++;
            it.avanzar();
        }

	return res;
}

bool Driver::esTagReciente(string t) {
	RedSocial::ItListaTags it = redSocial->tagsRecientes();
	while(it.hayMas()) {
		if (it.actual() == t)
			return true;
		it.avanzar();
	}
	return false;
}

int Driver::repeticionesRecientesTag(string t) {
	return redSocial->repeticionesRecientesTag(t);
}

Fecha Driver::ahora() {
	return Fecha(dia, ticks);
}


string Driver::mostrarMensaje(string autor, string texto, Lista<string> tags) {
	// usada para retornar strings en lugar de mensajes en la interfaz del Driver
	// No se debe alterar el formato generado
	ostringstream os;
	os << autor;
	os << "> ";
	os << texto;
	Lista<string>::Iterador it = tags.CrearIt();
	while (it.HaySiguiente()) {
		os << " #" << it.Siguiente();
		it.Avanzar();
	}
	return os.str();
}
